package com.kebabeaters.nakebab.client.presenter;

import java.util.ArrayList;
import java.util.List;

import com.google.gwt.event.shared.EventBus;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.view.client.SelectionChangeEvent;
import com.google.gwt.view.client.SelectionChangeEvent.Handler;
import com.google.gwt.view.client.SelectionChangeEvent.HasSelectionChangedHandlers;
import com.google.inject.Inject;
import com.gwtplatform.dispatch.shared.DispatchAsync;
import com.gwtplatform.mvp.client.Presenter;
import com.gwtplatform.mvp.client.View;
import com.gwtplatform.mvp.client.annotations.NameToken;
import com.gwtplatform.mvp.client.annotations.ProxyCodeSplit;
import com.gwtplatform.mvp.client.proxy.PlaceManager;
import com.gwtplatform.mvp.client.proxy.PlaceRequest;
import com.gwtplatform.mvp.client.proxy.ProxyPlace;
import com.gwtplatform.mvp.client.proxy.RevealContentEvent;
import com.kebabeaters.nakebab.client.place.NameTokens;
import com.kebabeaters.nakebab.client.place.ParamTokens;
import com.kebabeaters.nakebab.shared.action.tasterranking.GetTasterRankingAction;
import com.kebabeaters.nakebab.shared.action.tasterranking.TasterRankingEntry;
import com.kebabeaters.nakebab.shared.dto.structures.Mark;
import com.kebabeaters.nakebab.shared.dto.structures.Restaurant;

public class TasterKebabRankingPresenter
		extends
		Presenter<TasterKebabRankingPresenter.MyView, TasterKebabRankingPresenter.MyProxy> {

	public static class ListEntry {
		
		private int lp;
		private Restaurant restaurant;
		private List<Mark> marks;
		private int size;
		private double avg;
		
		public ListEntry(Restaurant r, List<Mark> m) {
			this.restaurant = r;
			this.marks = m;
			this.size = m.size();
			
			for (int i = 0; i < size; i++)
				avg += getMark(i);
			
			avg = avg / size;
		}
		
		public double getAvg() {
			return avg;
		}
		
		public String getRestaurant() {
			return restaurant.getName();
		}
		
		public double getMark(int i) {
			double avg = 0.0;
			Mark mark = marks.get(i);
			avg = mark.getBread() + mark.getMeat() + mark.getPriceForSize() + mark.getSauce() + mark.getVegetables();
			avg = avg / 5;
			
			return avg;
		}
		
		public String getTaster(int i) {
			return marks.get(i).getTaster().getName();
		}
		
		public void setLp(int i) {
			lp = i;
		}
		
		public int getLp() {
			return lp;
		}
		
		public int getSize() {
			return size;
		}
	}
	
	public interface MyView extends View {
		void createList(List<ListEntry> resultList);

		HasSelectionChangedHandlers getSelectionChangedHandler();

		ListEntry getSelectedObject();
	}

	private final DispatchAsync dispatcher;
	private final PlaceManager placeManager;
	private ListEntry selectedEntry;
	
	@ProxyCodeSplit
	@NameToken(NameTokens.tasterKebabRanking)
	public interface MyProxy extends ProxyPlace<TasterKebabRankingPresenter> {
	}

	@Inject
	public TasterKebabRankingPresenter(final EventBus eventBus, final MyView view,
			final MyProxy proxy, DispatchAsync dispatcher, PlaceManager placeManager) {
		super(eventBus, view, proxy);
		this.dispatcher = dispatcher;
		this.placeManager = placeManager;
	}

	@Override
	protected void revealInParent() {
		RevealContentEvent.fire(this, ContentPresenter.TYPE_Content, this);
	}
	
	@Override
	protected void onBind() {
		super.onBind();		
		
		getView().getSelectionChangedHandler().addSelectionChangeHandler(
				new Handler() {

					@Override
					public void onSelectionChange(SelectionChangeEvent event) {
						selectedEntry = getView().getSelectedObject();
						
						if (selectedEntry != null) {
							placeManager.revealPlace(new PlaceRequest(
									NameTokens.restaurantDetails).with(ParamTokens.id, selectedEntry.getRestaurant()));
						}
						
					}

				});
	}

	@Override
	protected void onReveal() {
		super.onReveal();
		getEntries();
	}
	
	private List<ListEntry> sortList(List<ListEntry> list) {
		List<ListEntry> result = new ArrayList<ListEntry>();
		
		ListEntry max = null;
		int size = list.size();
		for (int i = 0; i < size; i++) {
			max = list.get(0);
			for (ListEntry entry : list) {
				if (entry.getAvg() > max.getAvg())
					max = entry;
			}
			max.setLp(i + 1);
			result.add(max);
			list.remove(max);
		}
		
		return result;
	}
	
	private void getEntries() {
		dispatcher.execute(new GetTasterRankingAction(),
				new AsyncCallback<GetTasterRankingAction.Result>() {

					private List<TasterRankingEntry> resultList;

					@Override
					public void onFailure(Throwable caught) {
						caught.printStackTrace();
					}

					@Override
					public void onSuccess(GetTasterRankingAction.Result result) {
						resultList = result.getEntries();

						if (resultList == null) {
							System.out.println("Don't have any data");
						} else {							
							List<ListEntry> data = new ArrayList<ListEntry>();
							
							for (TasterRankingEntry entry: resultList)
								data.add(new ListEntry(entry.getRestaurant(), entry.getBestTastersMarks()));
							
							getView().createList(sortList(data));
						}
					}

				});
	}
}
